home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 1 / Meeting Pearls Vol 1 (1994).iso / installed_progs / util / shell+startup-tools / wbstart / wbstart-handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-03  |  11.8 KB  |  485 lines

  1. /*
  2.  * WBStart-Handler.c   V1.4
  3.  *
  4.  * Handler code
  5.  *
  6.  * (c) 1991-93 Stefan Becker
  7.  *
  8.  */
  9.  
  10. /* Handler includes */
  11. #include "WBStart.h"
  12.  
  13. /* System includes */
  14. #include <dos/dostags.h>
  15. #include <exec/memory.h>
  16. #include <workbench/icon.h>
  17. #include <workbench/workbench.h>
  18.  
  19. /* Prototypes */
  20. #include <clib/dos_protos.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/icon_protos.h>
  23. void _waitwbmsg(void);
  24.  
  25. /* Pragmas */
  26. #include <pragmas/dos_pragmas.h>
  27. #include <pragmas/exec_pragmas.h>
  28. #include <pragmas/icon_pragmas.h>
  29.  
  30. /* ANSI C includes */
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. /* Defines */
  35. #define MINSTACKSIZE 4096
  36.  
  37. /* Structure for path lists */
  38. struct PathList {
  39.                  BPTR NextPath; /* Pointer to next PathList */
  40.                  BPTR PathLock; /* Lock on directory */
  41.                 };
  42.  
  43. /* Library bases */
  44. extern struct Library *SysBase, *DOSBase, *IconBase;
  45.  
  46. /* Global data */
  47. static struct PathList *LoadPath=NULL; /* Path for loading programs */
  48. static struct MsgPort *HandlerPort;    /* Handler message port */
  49. static ULONG wbactive=0;               /* Number of active WB processes */
  50.  
  51. /* Version string */
  52. static const char Version[]="$VER: WBStart-Handler 1.4 ("
  53.                              __COMMODORE_DATE__ ")";
  54.  
  55. /* Duplicate a string */
  56. static char *StrDup(char *old)
  57. {
  58.  char *new;
  59.  
  60.  /* Allocate memory and copy string */
  61.  if (new=AllocVec(strlen(old)+1,MEMF_PUBLIC))
  62.   strcpy(new,old);
  63.  return(new);
  64. }
  65.  
  66. /* Try to load a program, return pointer to segment and lock to home dir */
  67. static BPTR LoadSegPath(char *name, BPTR curdir, BPTR *homedir)
  68. {
  69.  BPTR segment;
  70.  struct PathList *pl;
  71.  
  72.  /* Load from current directory */
  73.  if (segment=NewLoadSeg(name,NULL))
  74.   /* Copy lock */
  75.   if (*homedir=DupLock(curdir))
  76.    return(segment);
  77.   else
  78.    return(NULL); /* Error */
  79.  
  80.  /* Load from path */
  81.  pl=LoadPath;
  82.  while (pl) {
  83.   /* Set new directory */
  84.   CurrentDir(pl->PathLock);
  85.  
  86.   /* Try to load program */
  87.   if (segment=NewLoadSeg(name,NULL)) {
  88.    /* Return to old directory */
  89.    CurrentDir(curdir);
  90.  
  91.    /* Copy lock */
  92.    if (*homedir=DupLock(pl->PathLock))
  93.     return(segment);
  94.    else
  95.     return(NULL); /* Error */
  96.   }
  97.  
  98.   /* Next path entry */
  99.   pl=BADDR(pl->NextPath);
  100.  }
  101.  
  102.  /* Load from "C:" */
  103.  {
  104.   BPTR lock;
  105.  
  106.   /* Get directory lock */
  107.   if (lock=Lock("C:",ACCESS_READ)) {
  108.    CurrentDir(lock);
  109.  
  110.    /* Try to load program */
  111.    if (segment=NewLoadSeg(name,NULL)) {
  112.     /* Return to old directory */
  113.     CurrentDir(curdir);
  114.  
  115.     /* Set lock */
  116.     *homedir=lock;
  117.     return(segment);
  118.    }
  119.  
  120.    /* Free lock */
  121.    UnLock(lock);
  122.   }
  123.  }
  124.  
  125.  /* Return to old directory */
  126.  CurrentDir(curdir);
  127.  
  128.  /* Load failed */
  129.  return(NULL);
  130. }
  131.  
  132. /* Start program as a WB process */
  133. static BOOL StartProgram(struct WBStartMsg *msg)
  134. {
  135.  struct WBStartup *wbs;
  136.  
  137.  /* Allocate memory for WBStartup */
  138.  if (wbs=AllocVec(sizeof(struct WBStartup)+
  139.                   sizeof(struct WBArg)*(msg->wbsm_NumArgs+2),
  140.                   MEMF_PUBLIC|MEMF_CLEAR)) {
  141.   BPTR olddir,homedir;
  142.   char *toolname=msg->wbsm_Name;
  143.   char *projectname=NULL;
  144.   ULONG stacksize=msg->wbsm_Stack;
  145.  
  146.   /* Go to tools current directory */
  147.   olddir=CurrentDir(msg->wbsm_DirLock);
  148.  
  149.   /* Check for project icon */
  150.   {
  151.    struct DiskObject *dobj;
  152.  
  153.    /* Get program icon */
  154.    if ((dobj=GetDiskObject(toolname)) &&
  155.        (dobj->do_Type==WBPROJECT)) {
  156.     /* It's a project icon, get the name & icon of the default tool */
  157.     projectname=toolname;
  158.     if (toolname=StrDup(dobj->do_DefaultTool)) {
  159.      /* Free old icon */
  160.      FreeDiskObject(dobj);
  161.  
  162.      /* Get new icon */
  163.      dobj=GetDiskObject(toolname);
  164.     }
  165.    }
  166.  
  167.    /* No error and tool icon? */
  168.    if (toolname && dobj && (dobj->do_Type==WBTOOL)) {
  169.     /* Get stack size from tool icon */
  170.     if (dobj->do_StackSize>stacksize) stacksize=dobj->do_StackSize;
  171.  
  172.     /* Get tool window description (Maybe obsolete???) */
  173.     if (dobj->do_ToolWindow) wbs->sm_ToolWindow=StrDup(dobj->do_ToolWindow);
  174.    }
  175.  
  176.    /* Free Disk object */
  177.    if (dobj) FreeDiskObject(dobj);
  178.   }
  179.  
  180.   /* No error and can we load the program? */
  181.   if (toolname &&
  182.       (wbs->sm_Segment=LoadSegPath(toolname,msg->wbsm_DirLock,&homedir))) {
  183.    /* Program loaded */
  184.    struct WBArg *wbas;
  185.    struct WBArg *wbad;
  186.  
  187.    /* Build WBStartup message */
  188.    /* wbs->sm_Message.mn_Node.ln_Type=NT_MESSAGE; PutMsg() does this for us! */
  189.    wbs->sm_Message.mn_ReplyPort=HandlerPort;
  190.    wbs->sm_Message.mn_Length=sizeof(struct WBStartup);
  191.    wbs->sm_NumArgs=msg->wbsm_NumArgs+1;
  192.    wbs->sm_ArgList=(struct WBArg *)(wbs+1); /* WBArgs follow after WBStartup */
  193.  
  194.    /* Initialize WBArg list pointers */
  195.    wbas=msg->wbsm_ArgList; /* Source */
  196.    wbad=wbs->sm_ArgList;   /* Destination */
  197.  
  198.    /* The first argument is the tool itself. a) Copy lock */
  199.    if (wbad->wa_Lock=DupLock(homedir)) {
  200.     int i;
  201.  
  202.     /* b) Copy name */
  203.     wbs->sm_NumArgs=1;
  204.     if (wbad->wa_Name=(BYTE *) StrDup(toolname)) {
  205.      /* If it is a project, then use project as second argument */
  206.      if (!projectname ||
  207.           (wbs->sm_NumArgs=2, wbad++,
  208.            (wbad->wa_Lock=DupLock(msg->wbsm_DirLock)) &&
  209.            (wbad->wa_Name=(BYTE *) StrDup(projectname)))) {
  210.       BOOL noerror=TRUE;
  211.  
  212.       /* Next destination argument */
  213.       wbad++;
  214.  
  215.       /* Copy WBArgs from message */
  216.       for (i=msg->wbsm_NumArgs; i; i--,wbas++) {
  217.        char *argname=wbas->wa_Name;
  218.  
  219.        /* Copy lock (skip arguments with invalid locks) */
  220.        if ((wbad->wa_Lock=DupLock(wbas->wa_Lock)) ||
  221.  
  222.            /* NULL lock, check if argument name is a device name */
  223.            (argname && (argname[strlen(argname)-1]==':'))) {
  224.         /* Increment argument count */
  225.         wbs->sm_NumArgs++;
  226.  
  227.         /* Check & copy name */
  228.         if (!(argname && (wbad->wa_Name=(BYTE *) StrDup(argname)))) {
  229.          /* ERROR --> leave loop */
  230.          noerror=FALSE;
  231.          break;
  232.         }
  233.  
  234.         /* Next destination WBArg */
  235.         wbad++;
  236.        }
  237.       }
  238.  
  239.       /* No error? */
  240.       if (noerror) {
  241.        /* Make sure that the stack size is valid */
  242.        if (stacksize<MINSTACKSIZE) stacksize=MINSTACKSIZE;
  243.        stacksize=(stacksize+3)&(~3); /* Stack size must be a multiple of 4! */
  244.  
  245.        /* Create process */
  246.        Forbid(); /* We want to manipulate the process first! */
  247.        if (wbs->sm_Process=CreateProc(wbs->sm_ArgList->wa_Name,msg->wbsm_Prio,
  248.                                       wbs->sm_Segment,stacksize)) {
  249.         /* Set PROGDIR: *** ATTENTION: Don't try this at home, kids :-) *** */
  250.         {
  251.          struct Process *pr=(struct Process *) wbs->sm_Process->mp_SigTask;
  252.  
  253.          pr->pr_HomeDir=homedir;
  254.          pr->pr_WindowPtr=NULL;
  255.          pr->pr_ConsoleTask=NULL;
  256.         }
  257.         Permit(); /* Ready to rock'n'roll :-) */
  258.  
  259.         /* Send WBStartup message to new process */
  260.         PutMsg(wbs->sm_Process,(struct Message *) wbs);
  261.  
  262.         /* Free tool name */
  263.         if (projectname) FreeVec(toolname);
  264.  
  265.         /* Go back to old directory */
  266.         CurrentDir(olddir);
  267.  
  268.         /* Program successfully started! */
  269.         wbactive++;
  270.         return(TRUE);
  271.        } else
  272.         /* Couldn't create process */
  273.         Permit();
  274.       }
  275.      }
  276.     }
  277.  
  278.     /* Free WBArgs */
  279.     for (i=wbs->sm_NumArgs; i; i--, wbas++) {
  280.      /* Free lock */
  281.      UnLock(wbas->wa_Lock);
  282.  
  283.      /* Free name */
  284.      if (wbas->wa_Name) FreeVec(wbas->wa_Name);
  285.     }
  286.    }
  287.  
  288.    /* Free lock */
  289.    UnLock(homedir);
  290.  
  291.    /* Unload segment */
  292.    UnLoadSeg(wbs->sm_Segment);
  293.   }
  294.  
  295.   /* Free tool window description */
  296.   if (wbs->sm_ToolWindow) FreeVec(wbs->sm_ToolWindow);
  297.  
  298.   /* Free tool name */
  299.   if (projectname && toolname) FreeVec(toolname);
  300.  
  301.   /* Go back to old directory */
  302.   CurrentDir(olddir);
  303.   FreeVec(wbs);
  304.  }
  305.  
  306.  /* Call failed */
  307.  return(FALSE);
  308. }
  309.  
  310. /* Copy a path list */
  311. static BOOL CopyPathList(struct PathList **pla, struct PathList **plc,
  312.                          struct PathList *oldpl)
  313. {
  314.  struct PathList *pl1=oldpl,*pl2=*plc,*pl3=NULL;
  315.  
  316.  while (pl1) {
  317.   /* Get memory for path list entry */
  318.   if (!(pl3 || (pl3=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR))))
  319.    return(FALSE); /* No more memory... */
  320.  
  321.   /* Copy path entry */
  322.   if (pl3->PathLock=DupLock(pl1->PathLock)) {
  323.    /* Copy successful, append new entry to list. Head of list? */
  324.    if (*pla)
  325.     pl2->NextPath=MKBADDR(pl3); /* No, append it to list */
  326.    else
  327.     *pla=pl3;                   /* Yes, set list anchor */
  328.  
  329.    /* Save pointer */
  330.    pl2=pl3;
  331.  
  332.    /* Invalidate pointer, next time a new PathList will be allocated */
  333.    pl3=NULL;
  334.   }
  335.  
  336.   /* Get next path list entry */
  337.   pl1=BADDR(pl1->NextPath);
  338.  }
  339.  
  340.  /* Free memory */
  341.  if (pl3) FreeVec(pl3);
  342.  
  343.  /* All OK */
  344.  *plc=pl2; /* Save pointer to new end of list */
  345.  return(TRUE);
  346. }
  347.  
  348. /* Free a path list */
  349. static void FreePathList(struct PathList *pla)
  350. {
  351.  /* Check for NULL */
  352.  if (pla) {
  353.   struct PathList *pl1=pla,*pl2;
  354.  
  355.   /* Scan list */
  356.   do {
  357.    /* Get pointer to next entry */
  358.    pl2=BADDR(pl1->NextPath);
  359.  
  360.    /* Free entry */
  361.    UnLock(pl1->PathLock);
  362.    FreeVec(pl1);
  363.   } while (pl1=pl2);
  364.  }
  365. }
  366.  
  367. __stkargs void _main(int arglen, char *argptr)
  368. {
  369.  struct PathList *oldpath;
  370.  struct PathList *newpath=NULL;
  371.  struct CommandLineInterface *mycli;
  372.  
  373.  /* Check OS version */
  374.  if (SysBase->lib_Version<37) return;
  375.  
  376.  /* CLI Process? */
  377.  if (mycli=Cli()) {
  378.   /* Yes, try to copy path from Workbench process */
  379.   struct Process *wbproc=(struct Process *) FindTask("Workbench");
  380.  
  381.   /* Get pointer to our old path */
  382.   oldpath=(struct PathList *) BADDR(mycli->cli_CommandDir);
  383.   LoadPath=oldpath;
  384.  
  385.   /* Task found? Make sure it IS a process */
  386.   if (wbproc && (wbproc->pr_Task.tc_Node.ln_Type==NT_PROCESS)) {
  387.    /* It is a process */
  388.    struct CommandLineInterface *wbcli=BADDR(wbproc->pr_CLI);
  389.  
  390.    /* Make sure it IS a CLI process */
  391.    if (wbcli) {
  392.     struct PathList *dummy;
  393.  
  394.     /* Build new path: a) our old path, b) WB path */
  395.     if (CopyPathList(&newpath,&dummy,oldpath) &&
  396.         CopyPathList(&newpath,&dummy,
  397.                      (struct PathList *) BADDR(wbcli->cli_CommandDir))) {
  398.      /* Path successfully copied, install it in our process */
  399.      mycli->cli_CommandDir=MKBADDR(newpath);
  400.      LoadPath=newpath;
  401.     } else {
  402.      /* Error, free path list */
  403.      FreePathList(newpath);
  404.      return;
  405.     }
  406.    }
  407.   }
  408.  }
  409.  
  410.  /* Create message port */
  411.  if (HandlerPort=CreateMsgPort()) {
  412.   ULONG wsig,psig;
  413.   BOOL notend=TRUE;
  414.  
  415.   /* Make port public */
  416.   HandlerPort->mp_Node.ln_Pri=0;
  417.   HandlerPort->mp_Node.ln_Name=WBS_PORTNAME;
  418.   AddPort(HandlerPort);
  419.  
  420.   /* Init signal masks */
  421.   psig=1L<<HandlerPort->mp_SigBit;
  422.   wsig=psig|SIGBREAKF_CTRL_C;
  423.  
  424.   /* Main event loop */
  425.   while (notend) {
  426.    ULONG gotsigs;
  427.  
  428.    /* Wait on event */
  429.    gotsigs=Wait(wsig);
  430.  
  431.    /* Got a message at our port? */
  432.    if (gotsigs&psig) {
  433.     struct WBStartMsg *msg;
  434.  
  435.     /* Process all messages */
  436.     while (msg=(struct WBStartMsg *) GetMsg(HandlerPort))
  437.      /* Replied message? */
  438.      if (msg->wbsm_Msg.mn_Node.ln_Type==NT_REPLYMSG) {
  439.       /* This is the death message from a tool we started some time ago */
  440.       struct WBStartup *wbs=(struct WBStartup *) msg;
  441.       struct WBArg *wa=wbs->sm_ArgList;
  442.       int i=wbs->sm_NumArgs;
  443.  
  444.       while (i--) {
  445.        UnLock(wa->wa_Lock);      /* Free WB argument */
  446.        if (wa->wa_Name) FreeVec(wa->wa_Name);
  447.        wa++;
  448.       }
  449.  
  450.       if (wbs->sm_ToolWindow)     /* Free tool window specification */
  451.        FreeVec(wbs->sm_ToolWindow);
  452.  
  453.       UnLoadSeg(wbs->sm_Segment); /* Unload code */
  454.       FreeVec(wbs);               /* Free WBStartup */
  455.       wbactive--;                 /* One tool closed down */
  456.      } else {
  457.       /* We got a new message. Handle and reply it. */
  458.       msg->wbsm_Stack=StartProgram(msg);
  459.       ReplyMsg((struct Message *) msg);
  460.      }
  461.    }
  462.  
  463.    /* Received a CTRL-C? */
  464.    if ((gotsigs&SIGBREAKF_CTRL_C) && !wbactive) notend=FALSE;
  465.   }
  466.  
  467.   /* Exit handler */
  468.   RemPort(HandlerPort);
  469.   DeleteMsgPort(HandlerPort);
  470.  }
  471.  
  472.  /* Free path list */
  473.  if (newpath) {
  474.   /* Reinstall old path first */
  475.   mycli->cli_CommandDir=MKBADDR(oldpath);
  476.   FreePathList(newpath);
  477.  }
  478.  
  479.  /* Handler finished */
  480.  return;
  481.  
  482.  /* NOT REACHED */
  483.  _waitwbmsg();    /* Force linking of WB startup code */
  484. }
  485.